using System;
using System.Collections.Generic;
using System.Text;

namespace DatabaseCode.Data
{
  // Table は C++ コード上は構造体を指す。

  class D3_Table
  {
    // Parse メソッドでインスタンス化するので 非公開
    private D3_Table()
    {
      this.m_fields = new List<D4_Field>();
    }

    /*
   * 読み込む文字列の例
   * 
//払出
struct LotNo {
  int code;          // ★ ロットNoコード
  char no[kTextSize];// ロットNo
  int item_code;     // 品名コード ●Item.code

  bool IsEqualKey(const LotNo& r) { return r.code == code; }
};
   */
    //読み込むのは１つの struct のみ。
    //  戻り値：field が null で、文字列の終端に達した場合は true。
    //  ref int pos:文字列の読み込み開始位置。読み込んだ分上書きする。
    //  out D4_Field field：インスタンス化に失敗した場合は null にする。
    public static bool Parse(string str, ref int pos, out D3_Table table)
    {
      D3_Table t = new D3_Table();
      int len = str.Length;
      string temp;
      bool is_slash;
      bool is_braceclose;

      //コメントまで読み飛ばす
      is_slash = false;
      for (; pos < len; pos++)
      {
        if (is_slash)
        {
          if (str[pos] == '/') break;
          else is_slash = false; // 多分ここに来たら構文エラー。"  / /払出" みたいな
        }
        else
        {
          if (str[pos] == '/') is_slash = true;
        }
      }
      pos++;
      if (pos >= len) goto EndStr;

      //コメントを読み込む(例：払出）
      temp = "";
      for (; pos < len; pos++)
      {
        if (str[pos] == '\r')
        {
          pos++;
          break;
        }
        temp += str[pos];
      }
      if (pos >= len) goto EndStr;
      t.m_comment = temp;

      //struct を読み飛ばす
      for (; pos < len; pos++)
      {
        if (str[pos] == ' ') break;
      }
      pos++;
      if (pos >= len) goto EndStr;

      //テーブル名を読み込む（例：LotNo）
      temp = "";
      for (; pos < len; pos++)
      {
        if (!Utility.IsLetterOrDigit(str[pos])) break;
        temp += str[pos];
      }
      Utility.SkipLine(str, ref pos);
      if (pos >= len) goto EndStr;
      t.m_name = temp;

      // フィールドを読み込む
      for (; pos < len; pos++)
      {
        D4_Field f;
        if (D4_Field.Parse(str, ref pos, out f))
          break;

        if (f != null)
        {
          t.Add(f);
        }
        else
        {
          break;
        }
      }
      table = t;

      //構造体終了("};")まで読み飛ばす
      is_braceclose = false;
      for (; pos < len; pos++)
      {
        if (is_braceclose)
        {
          if (str[pos] == ';')
          {
            pos++;
            break;
          }
          else
          {
            is_braceclose = false;
          }
        }
        else
        {
          if (str[pos] == '}')
          {
            is_braceclose = true;
          }
        }
      }
      return false;

    EndStr:
      table = null;
      return true;
    }

    public bool FindReference(string findTable, string findMember,
                              out string referencedClass, out string referencedMember)
    {
      foreach (D4_Field field in m_fields)
      {
        if (field.IsEqualReference(findTable, findMember))
        {
          referencedClass = m_name;
          referencedMember = field.Variablename;
          return true;
        }
      }
      referencedClass = "";
      referencedMember = "";
      return false;
    }


    public string Comment
    {
      get
      {
        return m_comment;
      }
    }
    public string Name
    {
      get
      {
        return m_name;
      }
    }
    public List<D4_Field> Fields
    {
      get
      {
        return m_fields;
      }
    }
    public void Add(D4_Field f)
    {
      m_fields.Add(f);
    }

    private string m_comment;
    private string m_name;
    private List<D4_Field> m_fields;
  }
}
